package org.example;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

/**
 * 类描述：责任链模式
 * <br>
 *
 * @author ZS
 * @version 1.0
 * @date 2020/12/28
 **/
public class ChainOfResponsibility {

    public static void main(String[] args) {
        Request request = new Request(true, true, true, true, "请求");
        // 创建一个责任链
        FrequencyHandler handler = new FrequencyHandler(new LoginHandler());
        // 使用责任链处理请求
        if(handler.process(request)){
            System.out.println("请求成功！");
        } else {
            System.out.println("请求被拦截！");
        }
    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Accessors(chain = true)
    public static class Request {
        // 是否登录
        private boolean login;
        // 访问频率
        private boolean frequency;
        // 访问权限
        private boolean permission;
        // 敏感字
        private boolean containSensitiveWords;
        // 请求体
        private String requestBody;
    }

    // 责任链模式的处理器
    abstract static class Handler {
        // 指向下一个处理器
        Handler next;

        public Handler() {
            this(null);
        }

        // 传入下一个处理器
        public Handler(Handler next) {
            this.next = next;
        }

        public Handler getNext() {
            return next;
        }

        public void setNext(Handler next) {
            this.next = next;
        }

        abstract boolean process(Request request);
    }

    static class LoginHandler extends Handler {

        public LoginHandler() {
            super();
        }

        public LoginHandler(Handler handler) {
            super(handler);
        }

        @Override
        boolean process(Request request) {
            System.out.println("进入登录验证！");
            // 用户已登录
            if (request.isLogin()) {
                Handler next = getNext();
                // 不存在下一个处理结点
                if (null == next) {
                    return true;
                } else return next.process(request); //进入下一个处理单元
            }
            // 用户未登录
            System.out.println("用户未登录，拒绝请求！");
            return false;
        }
    }

    static class FrequencyHandler extends Handler {

        public FrequencyHandler() {
            super();
        }

        public FrequencyHandler(Handler next) {
            super(next);
        }

        @Override
        boolean process(Request request) {
            System.out.println("进入频率控制模块！");
            // 用户请求频率合乎要求
            if (request.isFrequency()) {
                Handler next = getNext();
                // 不存在下一个处理结点
                if (null == next) {
                    return true;
                } else return next.process(request); //进入下一个处理单元
            }
            System.out.println("用户请求过快，请稍后再试！");
            return false;
        }
    }

    static class PermissionHandler extends Handler {

        public PermissionHandler() {
            super();
        }

        public PermissionHandler(Handler next) {
            super(next);
        }

        @Override
        boolean process(Request request) {
            System.out.println("请入权限验证阶段！");
            if (request.isPermission()) {
                System.out.println("权限验证通过，允许访问！");
                Handler next = getNext();
                if (null == next) {
                    return true;
                } else return next.process(request);
            }
            System.out.println("权限验证失败！");
            return false;
        }
    }

    static class containSensitiveWords extends Handler {
        public containSensitiveWords() {
            super();
        }

        public containSensitiveWords(Handler next) {
            super(next);
        }

        @Override
        boolean process(Request request) {
            System.out.println("进入敏感词验证模块");
            if (request.isContainSensitiveWords()) {
                System.out.println("包含敏感词，拒绝访问！");
                return false;
            } else {
                Handler next = getNext();
                if (null == next) {
                    return true;
                }
                return next.process(request);
            }
        }
    }
}
